package netty.rpc.server;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import netty.rpc.client.InterfaceConfig;
import netty.rpc.client.RpcRequest;
import netty.rpc.core.RpcDecoder;
import netty.rpc.core.RpcEncode;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.context.ApplicationContext;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * @author Jim
 * @version 1.0.0
 * @descripition:
 * @date 2022/5/10 23:06
 */
public class NettyRpcServer {

    private static final Logger logger = LogManager.getLogger(NettyRpcServer.class);

    static  {
        //读取配置文件  rapidConfig.property
        InputStream is = NettyRpcServer.class.getClassLoader().getResourceAsStream("application-dev.yml");
        if (is != null){
            Properties properties = new Properties();
            try {
                properties.load(is);
                String portStr = properties.getProperty("port","9099");
                PORT = Integer.valueOf(portStr);
            } catch (IOException e) {
                logger.error("load application.yml error.", e);
            }finally {
                if (is != null){
                    try {
                        is.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }



    private static Integer PORT;

    private ApplicationContext applicationContext;

    public NettyRpcServer(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }


    /**
     * 接口配置list
     */
    private List<InterfaceConfig> interfaceConfigs = new CopyOnWriteArrayList<>();

    public void start(){
    logger.info("netty rpc server starting...");

        EventLoopGroup boss = new NioEventLoopGroup();
        EventLoopGroup worker = new NioEventLoopGroup();
        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(boss,worker)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            socketChannel.pipeline()
                                    .addLast(new RpcDecoder(RpcRequest.class))
                                    .addLast(new RpcEncode(RpcResponse.class))
                                    .addLast(new NettyRpcServerHandler(applicationContext));

                        }
                    })
                    .option(ChannelOption.SO_BACKLOG,128)
                    .childOption(ChannelOption.SO_KEEPALIVE, true);


                ChannelFuture future = serverBootstrap.bind(PORT).sync();
                logger.info("netty rpc server started successfully, listened[" + PORT + "]");
                future.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            logger.error("netty rpc server failed to start, listened[" + PORT + "]");
        }finally {
            boss.shutdownGracefully();
            worker.shutdownGracefully();
        }

    }



}
